package com.test.application.reflex_mechanism;


import lombok.SneakyThrows;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Arrays;

public class Reflex {
    @SneakyThrows
    public static void main(String[] args) {
        //反射获取对象class
        //方法1
        Class<?> aClass = Class.forName("com.test.application.reflex_mechanism.Dog");
        //方法2
//        aClass = Dog.class;

        //方法3
//        Dog dog = new Dog();
//        aClass = dog.getClass();
//        System.out.println(aClass);

        //反射构造对象
        //方法1
//        Object o = aClass.newInstance();
        //方法2
//        Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
//        Object o1 = declaredConstructor.newInstance();
//        System.out.println(o1);

        /**
         * 获取class对象的属性、方法、构造函数等
         */
        // 1. 获取class对象的成员变量
        Field[] allFields = aClass.getDeclaredFields();//获取class对象的所有属性
        Field[] publicFields = aClass.getFields();//获取class对象的public属性
        Field ageField = aClass.getDeclaredField("age");//获取class指定属性
        Field desField = aClass.getField("des");//获取class指定的public属性

        ///2. 获取class对象的方法
        Method[] methods = aClass.getDeclaredMethods();//获取class对象的所有声明方法
        Method[] allMethods = aClass.getMethods();//获取class对象的所有public方法 包括父类的方法
        Method method = aClass.getMethod("eat", String.class);//返回次Class对象对应类的、带指定形参列表的public方法
        System.out.println("method = " + method);
        Method declaredMethod = aClass.getDeclaredMethod("eat", String.class);//返回次Class对象对应类的、带指定形参列表的方法
        System.out.println("declaredMethod = " + declaredMethod);

        // 3.获取class对象的构造函数
        Constructor<?>[] allConstructors = aClass.getDeclaredConstructors();//获取class对象的所有声明构造函数
        Constructor<?>[] publicConstructors = aClass.getConstructors();//获取class对象public构造函数
        Constructor<?> constructor = aClass.getDeclaredConstructor();//获取指定声明构造函数
        Constructor publicConstructor = aClass.getConstructor(String.class, String.class);//获取指定声明的public构造函数


        //4.其他方法
        Annotation[] annotations = (Annotation[]) aClass.getAnnotations();//获取class对象的所有注解
        Annotation annotation = (Annotation) aClass.getAnnotation(Deprecated.class);//获取class对象指定注解

        Type genericSuperclass = aClass.getGenericSuperclass();//获取class对象的直接超类的 Type
        Type[] interfaceTypes = aClass.getGenericInterfaces();//获取class对象的所有接口的type集合

        //通过反射调用对象的方法
        Object o = aClass.newInstance();
        Method eat = aClass.getDeclaredMethod("eat", String.class);
        Object xxx = eat.invoke(o, "xxx");
        System.err.println("xxx = " + xxx);
    }
}
